Skip to content

Initial implementation#3

Merged
swissspidy merged 28 commits intomainfrom
copilot/scaffold-initial-implementation
Dec 19, 2025
Merged

Initial implementation#3
swissspidy merged 28 commits intomainfrom
copilot/scaffold-initial-implementation

Conversation

Copy link
Contributor

Copilot AI commented Dec 15, 2025

Implements a complete WP-CLI command for the WordPress AI Client library, including credential management and AI content generation capabilities with full Prompt_Builder API support.

Implementation

Credentials Management

  • Credentials_Command class with CRUD operations:

    • list - displays all stored credentials with masked API keys
    • get <provider> - retrieves specific provider credentials
    • set <provider> --api-key=<key> - stores/updates credentials
    • delete <provider> - removes credentials
  • Storage: Credentials persisted in wp_ai_client_provider_credentials WordPress option (matches API_Credentials_Manager)

  • Security: API keys masked in output (first 3 + last 4 chars visible)

  • Output formats: table, JSON, YAML, CSV via --format flag

AI Content Generation & Status

  • AI_Command class with generation and status operations:

    • status - displays table of supported AI capabilities (Text Generation, Image Generation)
    • generate text <prompt> - generates text from AI
    • generate image <prompt> - generates images from AI
    • check <prompt> - verifies if a prompt is supported for text/image generation
  • Complete Prompt_Builder API Integration with all configuration options:

    • --model=<models> - Comma-separated list of model preferences (e.g., "openai,gpt-4,anthropic,claude-3") → using_model_preference()
    • --provider=<provider> - Specific AI provider → using_provider()
    • --temperature=<temp> - Temperature control (0.0-2.0) → using_temperature()
    • --top-p=<top-p> - Top-p/nucleus sampling (0.0-1.0) → using_top_p()
    • --top-k=<top-k> - Top-k sampling (positive integer) → using_top_k()
    • --max-tokens=<tokens> - Maximum tokens to generate → using_max_tokens()
    • --system-instruction=<instruction> - System instruction to guide AI behavior → using_system_instruction()
    • --output=<file> - Save generated images to file
    • --format=<format> - Output format (text/json for generation, table/csv/json/yaml for status)
  • Security: Production-grade path validation, base64 strict validation, cross-platform system directory protection

  • Size limits: 50MB maximum for image data with configurable constants

Usage

# Check AI capabilities status
wp ai status

# Credentials management
wp ai credentials set openai --api-key=sk-proj-abc123
wp ai credentials list

# Text generation with sampling parameters
wp ai generate text "Write a story" --top-p=0.9 --top-k=40

# Text generation with all options
wp ai generate text "Explain AI" \
  --temperature=0.7 \
  --max-tokens=100 \
  --system-instruction="Explain as if to a 5-year-old"

# Image generation
wp ai generate image "A futuristic WordPress logo" --output=logo.png

# Check support
wp ai check "Summarize this text"

Security

  • Directory traversal prevention with full realpath() resolution
  • Cross-platform system directory write protection (Unix/Linux + Windows)
  • Base64 format validation with size limits
  • Safe path construction using resolved parent directory + basename
  • JSON encoding error handling
  • Input validation for all parameters

Testing

Comprehensive Behat test coverage for all commands including success/error paths, output formatting, validation scenarios, and edge cases.

Original prompt

This section details on the original issue you should resolve

<issue_title>Scaffold initial implementation</issue_title>
<issue_description>https://github.com/WordPress/wp-ai-client is an AI client and API for WordPress to communicate with any generative AI models of various capabilities using a uniform API.

Built on top of the PHP AI Client, adapted for the WordPress ecosystem.

It's proposed to be included in WordPress 7.0. Right now it's bundled with the AI Experiments plugin, but others can use it too via Composer. Its features:

  • WordPress-native Prompt Builder: Fluent API for building and configuring AI prompts
  • Automatic Credential Wiring: Automatic wiring up of AI provider API credentials based on storage in a WordPress database option.
  1. Credentials Management
    Command: wp ai credentials
    Manage the API keys stored in the wp_ai_client_provider_credentials option. See API_Credentials_Settings_Screen and API_Credentials_Manager.

    Note: this may be replaced with wp option * family of commands instead, but dedicated ones for AI might be easiest to get started

  • wp ai credentials list
    • Description: Lists all configured providers and their status (masked key).
    • Implementation: Fetch wp_ai_client_provider_credentials option. Use
      API_Credentials_Manager::get_all_cloud_providers_metadata() to cross-reference available providers vs. configured ones.
  • wp ai credentials get <provider_id>
    • Description: Get the API key for a specific provider.
    • Example: wp ai credentials get openai
  • wp ai credentials set <provider_id> <api_key>
    • Description: Set or update the API key for a provider.
    • Implementation: Fetch the option array, update the key for the provider ID, and write it back using update_option.
  • wp ai credentials delete <provider_id>
    • Description: Remove an API key.
  1. AI Generation
    Command: wp ai generate
    Execute a prompt using the AI_Client::prompt() fluent interface.

Notes: There are some open questions regarding output formats. Perhaps we start with dedicated wp ai generate-text and then later add wp ai generate-image. And wp ai generate could output whatever. Need to decide how to return images. Should they be saved to disk?

Also: when --debug=ai is used, we should print some addition debugging information such as model used, tokens used, etc. As provided by GenerativeAiResult from the PHP AI Client

  • Arguments:
    • : The text prompt to send.
  • Options (Flags mapping to Prompt_Builder methods):
    • --model=: Maps to using_model(). Should support a comma-separated list of models in order of preference
    • --provider=: Maps to using_provider().
    • --temperature=: Maps to using_temperature().
    • --max-tokens=: Maps to using_max_tokens().
    • --system-instruction=: Maps to using_system_instruction().
    • --format=<json|text>: Maps to as_json_response() or defaults to text.
  • Example:

1 wp ai generate "Write a haiku about WordPress" --provider=openai --temperature=0.7

  • Implementation:
    1. Call AI_Client::prompt( $prompt_arg ).
    2. Iterate over flags. If --temperature is set, call $builder->using_temperature( $val ).
    3. Call $builder->generate_text() and output the result.
  1. System Status & Diagnostics
    Command: wp ai status
    Check if the environment is ready for AI operations.
  • Description: Checks which capabilities are currently supported based on the environment and credentials.
  • Implementation:
    • Instantiate a builder: $builder = AI_Client::prompt();
    • Run checks:
      • Text Generation: + $builder->is_supported_for_text_generation()
      • Image Generation: + $builder->is_supported_for_image_generation()
    • Output a table of supported capabilities (Yes/No).

</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits December 15, 2025 23:02
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
Copilot AI changed the title [WIP] Add initial implementation for AI client in WordPress Implement wp ai credentials command for managing AI provider API keys Dec 15, 2025
Copilot AI requested a review from swissspidy December 15, 2025 23:07
@swissspidy

This comment was marked as resolved.

- Use wp_ai_client_provider_credentials option as per API_Credentials_Manager
- Add wp ai generate text/image commands for AI content generation
- Add wp ai check command to verify prompt support
- Add tests for new commands

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>

This comment was marked as resolved.

Copilot AI and others added 5 commits December 15, 2025 23:26
- Add proper type hints for Prompt_Builder parameters
- Use json_encode instead of wp_json_encode for consistency
- Add path validation for image output to prevent writing to system directories
- Use strict base64 decoding for better error handling

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
- Check for directory traversal (..) before resolving paths
- Validate base64 format with regex before decoding
- Add size limit check (50MB) to prevent memory exhaustion
- Verify parent directory exists before attempting file write
- Improve error messages for better debugging

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
…stant

- Replace regex validation with PHP's native base64_decode strict mode
- Add MAX_IMAGE_SIZE_BASE64 constant for clarity and maintainability
- Simplify base64 validation logic to rely on built-in strict validation
- Improve error messages for better user feedback

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
- Use realpath() to fully resolve paths and prevent all traversal attacks (including URL-encoded)
- Reconstruct safe output path using resolved parent dir + basename
- Add json_encode() error handling with descriptive messages
- Ensure is_dir() check for parent directory validation

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
- Add Windows system directory protection (C:\Windows, C:\Program Files)
- Use case-insensitive path comparison for Windows compatibility
- Separate MAX_IMAGE_SIZE_BYTES constant for better clarity
- Improve documentation for size constants with detailed explanation

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
Copilot AI changed the title Implement wp ai credentials command for managing AI provider API keys Implement complete wp ai command with credentials management and content generation Dec 15, 2025
@swissspidy

This comment was marked as resolved.

- Add --provider flag mapping to using_provider()
- Update --model flag to support comma-separated list of model preferences
- Add --max-tokens flag mapping to using_max_tokens()
- Add --system-instruction flag mapping to using_system_instruction()
- Add validation tests for new options
- Update documentation with examples for all new flags

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>

This comment was marked as resolved.

Copilot AI and others added 2 commits December 15, 2025 23:43
- Replace call_user_func_array with spread operator syntax
- Cleaner and more readable code
- Better performance with modern PHP

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
- Remove trailing whitespace for coding standards compliance
- Cache count() result before loop to avoid repeated function calls
- Minor performance and style improvements

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
@swissspidy

This comment was marked as resolved.

- Implement status command to display table of supported AI capabilities
- Check text generation and image generation support
- Support multiple output formats (table, csv, json, yaml)
- Add test scenario for status command
- Update class documentation with status command example

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>

This comment was marked as resolved.

Copilot AI and others added 4 commits December 16, 2025 00:00
- Add ensure_ai_client_available() helper method to follow DRY principle
- Update generate, check, and status methods to use helper
- Add CAPABILITY_CHECK_PROMPT constant for clarity
- Improve code maintainability and reduce duplication

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
- Extract FORBIDDEN_PATHS constant for better maintainability
- Improve comment conciseness
- Use case-sensitive check for Unix paths, case-insensitive for Windows
- Prevent false positives on case-sensitive filesystems

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
- Use more robust Windows path detection (checks for :\\ instead of C:\\)
- Handles all drive letters (D:\\, E:\\, etc.)
- Clarify comment about using constant for consistency

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
- Clarify that capability detection is based on configured providers
- Document that prompt content doesn't affect capability detection logic
- Improve code documentation for better understanding

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
@codecov
Copy link

codecov bot commented Dec 18, 2025

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@swissspidy
Copy link
Member

@copilot Add new args for the generation command:

  • --top-p (using_top_p(float $top_p)
  • --top-k (using_top_k(int $top_k=k)

- Add --top-p flag for nucleus sampling (value between 0.0 and 1.0)
- Add --top-k flag for top-k sampling (positive integer)
- Map to using_top_p() and using_top_k() Prompt_Builder methods
- Add validation for both parameters
- Add example usage in documentation
- Add Behat tests for parameter validation

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Dec 18, 2025

@copilot Add new args for the generation command:

  • --top-p (using_top_p(float $top_p)
    ...

Added --top-p and --top-k parameters in commit 2fff296:

Features:

  • --top-p=<top-p> - Top-p/nucleus sampling parameter (0.0-1.0) → using_top_p()
  • --top-k=<top-k> - Top-k sampling parameter (positive integer) → using_top_k()
  • Both include validation with clear error messages
  • Added example: wp ai generate text "Write a story" --top-p=0.9 --top-k=40
  • Comprehensive Behat test coverage for parameter validation

@swissspidy swissspidy changed the title Implement complete wp ai command with credentials management and content generation Initial implementation Dec 19, 2025
@swissspidy swissspidy marked this pull request as ready for review December 19, 2025 09:34
@swissspidy swissspidy merged commit 6a147ac into main Dec 19, 2025
37 checks passed
@swissspidy swissspidy deleted the copilot/scaffold-initial-implementation branch December 19, 2025 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scaffold initial implementation

2 participants